<?php

namespace IYUU\sdk\CoolQ\Modules\system;

use BadRequestException;
use IYUU\sdk\CoolQ\Context;
use IYUU\sdk\CoolQ\Event\Message as EventMessage;
use IYUU\sdk\CoolQ\Modules\system\Domain\BannedWords;
use IYUU\sdk\CoolQ\Modules\system\Domain\BasicReply;
use IYUU\sdk\CoolQ\Modules\system\Domain\BlackList;
use IYUU\sdk\CoolQ\Modules\system\Domain\CreditsExchange;
use IYUU\sdk\CoolQ\ModulesDomainInterface;
use IYUU\sdk\CoolQ\ModulesProcessor;
use function IYUU\sdk\CoolQ\showTable;

/**
 * 系统管理
 * Class processor
 * @package IYUU\sdk\CoolQ\Modules\userapi
 */
class processor extends ModulesProcessor
{
    /**
     * 上下文中HOOK的逻辑类
     */
    const hook_domain_class = 'route_domain_class';
    /**
     * 注册提供者
     * @var string[]
     */
    protected $provider = [
        BlackList::class,
        BannedWords::class,
        BasicReply::class,
        CreditsExchange::class,
    ];

    /**
     * 应答方法
     * @param Context $context
     * @param EventMessage $msgObj
     * @return array
     * @throws BadRequestException
     */
    public function respond(Context $context, EventMessage $msgObj): array
    {
        // 必须工作人员，才能进行的操作
        $msgObj->requireWorker();

        // 消息内容
        $message = $context->get('message');
        if ($this->inContext()) {
            /**
             * 结束上下文
             */
            if (in_array($message, ['exit', '取消', '退出', '算了'])) {
                $this->endContext();
                return EventMessage::reply('成功退出上下文');
            }
        } else {
            /**
             * 开启上下文
             * - 按照规则触发到本模块, 先启动上下文来锁定会话, 以保证下次回复依然执行到本模块
             */
            $this->beginContext();
        }

        /**
         * 创建提供者对象，检查状态/提取关键字/显示二级菜单/刷新上下文/hook逻辑类
         */
        $keywords = [];
        $domains = [];
        $providers = [];
        foreach ($this->provider as $index => $class_name) {
            /** @var ModulesDomainInterface $domain */
            $domain = new $class_name();
            if ($domain->state()) {
                $keywords[] = $domain->keyword();
                $domains[] = $domain;
                $providers[get_class($domain)] = $domain;
                if ($reply = $domain->menu($message)) {
                    return $this->showTwoMenu($reply, $domain);
                }
            }
            /**
             * 二级菜单，支持数字
             */
            if (is_numeric($message) && (($index + 1) === count($this->provider))) {
                //消息为数字 && 迭代至数组最后一个元素
                $i = (int)$message;
                if ((0 < $i) && ($i <= count($keywords))) {
                    $message = $keywords[$i - 1];
                    $domain = $domains[$i - 1];
                    if ($reply = $domain->menu($message)) {
                        return $this->showTwoMenu($reply, $domain);
                    }
                } else {
                    return EventMessage::replyGroup('不存在的菜单索引：' . $message, false, true);
                }
            }
        }

        /**
         * 至少开启一个逻辑模块
         */
        if (empty($keywords)) {
            return EventMessage::replyGroup('至少开启一个逻辑模块');
        }

        /**
         * 显示主菜单
         */
        if ($message === '菜单' || $message === '群管菜单') {
            return EventMessage::reply(showTable($keywords) . PHP_EOL . date('Y-m-d H:i:s'));
        }

        /**
         * 执行命令
         */
        $inContext = $this->getContextSession(); // 模块的上下文Session
        if (!empty($inContext) && !empty($inContext['data'][self::hook_domain_class])) {
            //HOOK的包含命名空间的完整类名
            $hook_domain_class = $inContext['data'][self::hook_domain_class];
            if (isset($providers[$hook_domain_class])) {
                $hook_domain = $providers[$hook_domain_class];
                // 刷新上下文有效期
                $this->refreshContext();
                // 调用Domain方法
                $result = $hook_domain->process($context, $msgObj);
                if (!empty($result)) {
                    if ($msgObj->isPrivate()) {
                        //$msgObj->sendPM($result);
                        return EventMessage::reply($result);
                    } else {
                        return EventMessage::replyGroup($result, false, true);
                    }
                }
            }
        }

        return EventMessage::reply(__METHOD__ . "关键字：{$message}，未匹配到处理结果" . PHP_EOL . '退出：exit');
    }

    /**
     * 显示二级菜单
     * @param string $reply
     * @param ModulesDomainInterface $domain
     * @return array
     */
    private function showTwoMenu(string $reply, ModulesDomainInterface $domain): array
    {
        //HOOK的包含命名空间的完整类名
        $this->refreshContext(120, [self::hook_domain_class => get_class($domain)]);
        return EventMessage::replyGroup($reply);
    }
}
